/****************************************************
 * 用于练习非阻塞IO代码
 * 采用fcntl函数，通过设置文件描述符的等待属性完成非阻塞式IO
 * 我们当然也可以在recv/read，send/write这里设置非阻塞的属性
 * 但是通过修改fd属性，更直观且一步到位
 *****************************************************/
#include <iostream>

#include <cstring>
#include <cstdlib>
#include <cerrno>

#include <unistd.h>
#include <fcntl.h>
void SetNoBlock()
{
    int old_file_status = fcntl(0, F_GETFL);
    if (old_file_status == -1)
    {
        std::cout << "fcntl F_GETFL error" << std::endl;
        exit(-1);
    }
    int ret_fcntl = fcntl(0, F_SETFL, old_file_status | O_NONBLOCK);
    if (ret_fcntl == -1)
    {
        std::cout << "fcntl F_SETFL error" << std::endl;
        exit(-1);
    }
}
const static int buffer_size = 1024;
int main()
{
    // 设置文件状态为非阻塞IO
    SetNoBlock();
    // 这里使用stdin测试，fd = 0
    char buffer[buffer_size];
    while (true)
    {
        int ret = read(0, buffer, sizeof(buffer) - 1);
        // 读取成功
        if (ret > 0)
        {
            buffer[ret] = '\0';
            std::cout << buffer << std::endl;
        }
        // 读到末尾
        else if (ret == 0)
        {
            std::cout << "read end" << std::endl;
            break;
        }
        // 读取失败 / 无数据
        else
        {
            if(errno == EWOULDBLOCK)
            {
                std::cout << "no data..." << std::endl;
            }
            else if(errno == EINTR)
            {
                std::cout << "被信号中断, 已恢复正常" << std::endl;
            }
            else
            {
                std::cout << "read error" << std::endl;
                break;
            }
        }
        sleep(1);
    }
    return 0;
}